package Eyjafjalla.helper;

import Eyjafjalla.card.AbstractEyjafjallaCard;
import Eyjafjalla.card.attack.UrgentPresto_Eyjafjalla;
import Eyjafjalla.card.skill.*;
import Eyjafjalla.card.status.Burn_Eyjafjalla;
import Eyjafjalla.modcore.EyjafjallaTag;
import Eyjafjalla.patch.CloudPatch;
import Eyjafjalla.patch.MelodyPatch;
import Eyjafjalla.power.AfterImageFixPower;
import Eyjafjalla.relic.ShallowSong;
import Eyjafjalla.subscriber.MelodySubscriber;
import basemod.ReflectionHacks;
import com.megacrit.cardcrawl.actions.common.ApplyPowerAction;
import com.megacrit.cardcrawl.actions.common.ReducePowerAction;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.blue.Buffer;
import com.megacrit.cardcrawl.cards.blue.HelloWorld;
import com.megacrit.cardcrawl.cards.blue.MachineLearning;
import com.megacrit.cardcrawl.cards.green.AfterImage;
import com.megacrit.cardcrawl.cards.green.Caltrops;
import com.megacrit.cardcrawl.cards.green.Envenom;
import com.megacrit.cardcrawl.cards.green.Footwork;
import com.megacrit.cardcrawl.cards.red.DemonForm;
import com.megacrit.cardcrawl.cards.red.FeelNoPain;
import com.megacrit.cardcrawl.cards.red.Inflame;
import com.megacrit.cardcrawl.cards.red.Metallicize;
import com.megacrit.cardcrawl.cards.status.Burn;
import com.megacrit.cardcrawl.core.AbstractCreature;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.monsters.AbstractMonster;
import com.megacrit.cardcrawl.powers.*;

import java.util.ArrayList;
import java.util.Iterator;

public class EyjafjallaHelper {

    private static final ArrayList<AbstractCard> dollyCards;
    private static final ArrayList<AbstractCard> cakePowers;
    private static final ArrayList<MelodySubscriber> melodies;

    public static void IncreaseCard(AbstractCard card,int d,int b,int m,int c){
        card.baseDamage += d;
        if(card.baseDamage<0&&d!=0)
            card.baseDamage = 0;
        card.baseBlock += b;
        if(card.baseBlock<0&&b!=0)
            card.baseBlock = 0;
        card.baseMagicNumber += m;
        if(card.baseMagicNumber<0&&m!=0)
            card.baseMagicNumber = 0;
        card.magicNumber = card.baseMagicNumber;
        if(card.cost>=0&&c!=0)
            card.updateCost(c);
    }

    public static AbstractCard getRandomDollyCard(boolean inCombat){
        int random = 0;
        if(inCombat){
            random = AbstractDungeon.cardRandomRng.random(dollyCards.size()-1);
        }
        else {
            random = AbstractDungeon.cardRng.random(dollyCards.size()-1);
        }
        return dollyCards.get(random);
    }

    private static void initCakePowers(){
        AbstractCard feel = new FeelNoPain();
        feel.baseMagicNumber = 2;
        feel.magicNumber = 2;
        cakePowers.add(feel);
        cakePowers.add(new Inflame());
        cakePowers.add(new Metallicize());
        AbstractCard demon = new DemonForm();
        demon.baseMagicNumber = 1;
        demon.magicNumber = 1;
        cakePowers.add(demon);
        cakePowers.add(new Footwork());
        cakePowers.add(new Caltrops());
        cakePowers.add(new Envenom());
        cakePowers.add(new AfterImage());
        cakePowers.add(new Buffer());
        cakePowers.add(new MachineLearning());
        cakePowers.add(new HelloWorld());
    }

    public static void initMelodies(){
        melodies.add(new UrgentPresto_Eyjafjalla());
        melodies.add(new TreeAngle_Eyjafjalla());
        melodies.add(new Sailing_Eyjafjalla());
        melodies.add(new InSunset_Eyjafjalla());
        melodies.add(new GoldAndRoses_Eyjafjalla());
        melodies.add(new ShallowSong());
        melodies.add(new BlazePrelude_Eyjafjalla());
    }

    public static MelodyPatch.MelodySingle getRandomMelody(){
        int random = AbstractDungeon.cardRandomRng.random(melodies.size()-1);
        return melodies.get(random).getSingle();
    }

    public static ArrayList<AbstractCard> getDollyCards(boolean inCombat,int count){
        ArrayList<AbstractCard> tmp = new ArrayList<>();
        if(count>=dollyCards.size()){
            for(int i =0;i<dollyCards.size();i++){
                tmp.add(dollyCards.get(i).makeStatEquivalentCopy());
            }
        }
        else {
            ArrayList<AbstractCard> total = new ArrayList<>(dollyCards);
            if(!inCombat){
                for(int i =0;i<count;i++){
                    AbstractCard c = total.remove(AbstractDungeon.cardRng.random(total.size()-1));
                    tmp.add(c.makeStatEquivalentCopy());
                }
            }
            else {
                for(int i =0;i<count;i++){
                    AbstractCard c = total.remove(AbstractDungeon.cardRandomRng.random(total.size()-1));
                    tmp.add(c.makeStatEquivalentCopy());
                }
            }
        }

        return tmp;
    }

    public static ArrayList<AbstractCard> getDollyCards(boolean inCombat, int count, AbstractCard.CardRarity rarity){
        ArrayList<AbstractCard> tmp = new ArrayList<>();
        ArrayList<AbstractCard> total = new ArrayList<>();
        for(AbstractCard c:dollyCards){
            if(c.rarity==rarity)
                total.add(c);
        }
        if(count>=total.size()){
            for(int i =0;i<total.size();i++){
                tmp.add(total.get(i).makeStatEquivalentCopy());
            }
        }
        else {
            if(!inCombat){
                for(int i =0;i<count;i++){
                    AbstractCard c = total.remove(AbstractDungeon.cardRng.random(total.size()-1));
                    tmp.add(c.makeStatEquivalentCopy());
                }
            }
            else {
                for(int i =0;i<count;i++){
                    AbstractCard c = total.remove(AbstractDungeon.cardRandomRng.random(total.size()-1));
                    tmp.add(c.makeStatEquivalentCopy());
                }
            }
        }

        return tmp;
    }

    public static ArrayList<AbstractCard> getCakeCards(int count){
        ArrayList<AbstractCard> tmp = new ArrayList<>();
        if(count>=cakePowers.size()){
            for(int i =0;i<cakePowers.size();i++){
                tmp.add(cakePowers.get(i).makeStatEquivalentCopy());
            }
        }
        else {
            ArrayList<AbstractCard> total = new ArrayList<>(cakePowers);
            for(int i =0;i<count;i++){
                AbstractCard c = total.remove(AbstractDungeon.cardRandomRng.random(total.size()-1));
                tmp.add(c.makeStatEquivalentCopy());
            }
        }

        return tmp;
    }

    public static void setCakePowerToCreature(AbstractCard c, AbstractCreature target){
        switch (c.cardID){
            case FeelNoPain.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new FeelNoPainPower(target,2),2));
                break;
            }
            case Inflame.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new StrengthPower(target,c.magicNumber),c.magicNumber));
                break;
            }
            case Metallicize.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new MetallicizePower(target,c.magicNumber),c.magicNumber));
                break;
            }
            case DemonForm.ID:{
                if(!target.isPlayer){
                    RitualPower r = new RitualPower(target,1,false);
                    ReflectionHacks.setPrivate(r,RitualPower.class,"skipFirst",false);
                    AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,r,1));
                }
                else {
                    AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new DemonFormPower(target,1),1));
                }
                break;
            }
            case Footwork.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new DexterityPower(target,c.magicNumber),c.magicNumber));
                break;
            }
            case Caltrops.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new ThornsPower(target,c.magicNumber),c.magicNumber));
                break;
            }
            case Envenom.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new EnvenomPower(target,1),1));
                break;
            }
            case AfterImage.ID:{
                if(!target.isPlayer)
                    AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new AfterImageFixPower(target,1),1));
                else {
                    AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new AfterImagePower(target,1),1));
                }
                break;
            }
            case Buffer.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new BufferPower(target,c.magicNumber),c.magicNumber));
                break;
            }
            case MachineLearning.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new DrawPower(target,1),1));
                break;
            }
            case HelloWorld.ID:{
                AbstractDungeon.actionManager.addToTop(new ApplyPowerAction(target,target,new HelloPower(target,1),1));
                break;
            }
        }
    }

    public static int markCardToFire(AbstractCard card,int totalAmt){
        if(!CloudPatch.CloudField.showFire.get(card)){
            return 0;
        }
        if(card.tags.contains(EyjafjallaTag.UNLIMITED_FIRE_EYJAFJALLA)){
            CloudPatch.CloudField.isFire.set(card, true);
            if(card instanceof AbstractEyjafjallaCard){
                AbstractEyjafjallaCard e = (AbstractEyjafjallaCard) card;
                e.baseFire += totalAmt;
                e.fire = e.baseFire;
            }
            card.initializeDescription();
            return totalAmt;
        }
        else {
            if (!CloudPatch.CloudField.isFire.get(card)) {
                CloudPatch.CloudField.isFire.set(card, true);
                card.initializeDescription();
                return 1;
            }
        }
        return 0;
    }

    public static void unmarkCardToFire(AbstractCard card){
        if(card.tags.contains(EyjafjallaTag.UNLIMITED_FIRE_EYJAFJALLA)){
            CloudPatch.CloudField.isFire.set(card, false);
            if(card instanceof AbstractEyjafjallaCard){
                AbstractEyjafjallaCard e = (AbstractEyjafjallaCard) card;
                e.baseFire = 0;
                e.fire = e.baseFire;
            }
            card.initializeDescription();
        }
        else {
            if (CloudPatch.CloudField.isFire.get(card)) {
                CloudPatch.CloudField.isFire.set(card, false);
                card.initializeDescription();
            }
        }
    }

    public static boolean hasFireableCards(){
        Iterator var2 = AbstractDungeon.player.masterDeck.group.iterator();

        while (var2.hasNext()) {
            AbstractCard c = (AbstractCard) var2.next();
            if ((c.type == AbstractCard.CardType.ATTACK || c.type == AbstractCard.CardType.SKILL || c.type == AbstractCard.CardType.POWER) && (!CloudPatch.CloudField.isFire.get(c)||c.hasTag(EyjafjallaTag.UNLIMITED_FIRE_EYJAFJALLA)) && CloudPatch.CloudField.showFire.get(c)) {
                return true;
            }
        }
        return false;
    }

    public static int countBurnCards() {
        int count = 0;
        Iterator var1 = AbstractDungeon.player.hand.group.iterator();

        AbstractCard c;
        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                ++count;
            }
        }

        var1 = CloudPatch.cloudGroup.group.iterator();
        while (var1.hasNext()){
            c = (AbstractCard) var1.next();
            if(isBurn(c))
                ++count;
        }

        var1 = AbstractDungeon.player.drawPile.group.iterator();

        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                ++count;
            }
        }

        var1 = AbstractDungeon.player.discardPile.group.iterator();

        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                ++count;
            }
        }

        return count;
    }

    public static int countBurnUpgrades(){
        int count = 0;
        Iterator var1 = AbstractDungeon.player.hand.group.iterator();

        AbstractCard c;
        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                count+=getUpgrade(c);
            }
        }

        var1 = CloudPatch.cloudGroup.group.iterator();
        while (var1.hasNext()){
            c = (AbstractCard) var1.next();
            if(isBurn(c))
                count+=getUpgrade(c);
        }

        var1 = AbstractDungeon.player.drawPile.group.iterator();

        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                count+=getUpgrade(c);
            }
        }

        var1 = AbstractDungeon.player.discardPile.group.iterator();

        while(var1.hasNext()) {
            c = (AbstractCard)var1.next();
            if (isBurn(c)) {
                count+=getUpgrade(c);
            }
        }

        return count;
    }

    public static boolean isBurn(AbstractCard card){
        return card.cardID.equals(Burn.ID) || card.cardID.equals(Burn_Eyjafjalla.ID);
    }

    public static int getUpgrade(AbstractCard card){
        int count = 0;
        if(card.cardID.equals(Burn.ID)&&card.upgraded)
            count++;
        else if(card.cardID.equals(Burn_Eyjafjalla.ID))
            count+=card.timesUpgraded;
        return count;
    }

    static {
        dollyCards = StringHelper.getDollyCardsToAdd();
        cakePowers = new ArrayList<>();
        initCakePowers();
        melodies = new ArrayList<>();
        initMelodies();
    }
}
